namespace Radar.Test
{
    using System;
    using Moq;
    using NUnit.Framework;

    [TestFixture]
    public class IocConfigurationTest
    {
        private class L : Lifetime
        {
            protected override Func<ResolveContext, object> GetBuilderInternal(Func<ResolveContext, object> initialBuild)
            {
                throw new NotImplementedException();
            }
        }

        private IocConfiguration configuration;
        private Mock<IContainer> container;

        [SetUp]
        public void SetUp()
        {
            container = new Mock<IContainer>();

            configuration = new IocConfiguration(container.Object);
        }

        [Test]
        public void WillSetLifetime()
        {
            var lifetime = new L();

            configuration.WithLifetime(lifetime);

            Assert.That(configuration.Lifetime, Is.EqualTo(lifetime));
        }

        [Test]
        public void WillSetConstantParameterForSpecifiedKey()
        {
            const string param = @"some parameter";
            var value = new object();

            configuration.WithValue(param, value);

            var result = configuration.Parameters[param]();

            Assert.That(result, Is.EqualTo(value));
        }

        [Test]
        public void WillSetCustomDependencyForSpecifiedKey()
        {
            const string param = @"some parameter";
            const string value = @"some value";

            var o = new object();
            container.Setup(x => x.Resolve(value)).Returns(o);

            configuration.WithDependency(param, value);

            var result = configuration.Parameters[param]();

            container.VerifyAll();

            Assert.That(result, Is.EqualTo(o));
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void WillThrowConstructorOnNullContainer()
        {
            new IocConfiguration(null);
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void WillThrowOnEmptyParameterWhenSettingDependency()
        {
            configuration.WithDependency(string.Empty, "some key");
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void WillThrowOnEmptyKeyWhenSettingDependency()
        {
            configuration.WithDependency("a", string.Empty);
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void WillThrowOnEmptyParameterWhenSettingValue()
        {
            configuration.WithValue(string.Empty, new object());
        }

        [Test]
        public void NoExceptionsOnNullValueWhenSettingValue()
        {
            configuration.WithValue("a", null);
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void WillThrowOnSettingNullLifetime()
        {
            configuration.WithLifetime(null);
        }
    }
}